package com.violet.uaa.server.security.factory;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.violet.auth.client.util.AuthUtils;
import com.violet.common.constant.universal.SecurityConstants;
import com.violet.uaa.server.login.service.VioletUserDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 类说明: 用户service工厂
 *
 * @author wqf
 * @date 2024/8/30 16:27
 */
@Slf4j
@Service
public class UserDetailServiceFactory {

    private static final String ERROR_MSG = "找不到账号类型为 {} 的实现类";

    @Resource
    private List<VioletUserDetailsService> userDetailsServices;

    /**
     * CustomAuthenticationDetailsSource 类中对认证信息补充了账户类型信息
     * 所以这里可以获取到账户类型
     */
    public VioletUserDetailsService getService(Authentication authentication) {
        String accountType = AuthUtils.getAccountType(authentication);
        return this.getService(accountType);
    }

    /**
     * 方法描述: 根据账号类型获取对应的认证service
     * 比如账号密码登录、手机号登录等可能要走不同的认证逻辑
     * 所以获取不用的service去处理对应的业务逻辑
     * @param accountType 账户类型
     * @return com.violet.uaa.server.login.service.VioletUserDetailsService
     * @author wqf
     * @date 2024/9/3 15:48
     */
    public VioletUserDetailsService getService(String accountType) {
        if (accountType == null) {
            //默认pc端登录
            accountType = SecurityConstants.DEF_ACCOUNT_TYPE;
        }
        log.info("UserDetailServiceFactory.getService:{}", accountType);
        if (CollUtil.isNotEmpty(userDetailsServices)) {
            for (VioletUserDetailsService userService : userDetailsServices) {
                if (userService.supports(accountType)) {
                    return userService;
                }
            }
        }
        throw new InternalAuthenticationServiceException(StrUtil.format(ERROR_MSG, accountType));
    }
}
